package cn.zhyjohn.paysystem.drud;

import cn.hutool.json.JSONObject;
import cn.zhyjohn.paysystem.bean.AliPayBean;
import cn.zhyjohn.paysystem.utils.Response;
import cn.zhyjohn.paysystem.requset.AliPayParams;
import cn.zhyjohn.paysystem.requset.AliTradePayParams;
import cn.zhyjohn.paysystem.requset.AliTradePrecreateParams;
import cn.zhyjohn.paysystem.requset.AliTradeRefundParams;
import cn.zhyjohn.paysystem.service.AlipayService;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.*;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.ijpay.alipay.AliPayApi;
import com.ijpay.alipay.AliPayApiConfig;
import com.ijpay.alipay.AliPayApiConfigKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @author JOHN
 * @title: AlipayDrud
 * @projectName paysystem
 * @since 2019/8/29
 */
@Slf4j
@Service
public class AlipayDrud implements AlipayService {
    /**
     * 通知地址
     */
    private String notify_url = "/alipay/notify_url";
    /**
     * 返回地址
     */
    private String return_url = "/alipay/return_url";

    @Autowired
    private AliPayBean aliPayBean;

    @PostConstruct
    private void init() {
        AliPayApiConfig aliPayApiConfig = getAliPayApiConfig();
        AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig);
        log.info("初始化支付宝配置");
    }

    @PreDestroy
    private void destroy() {
        AliPayApiConfigKit.removeThreadLocalAppId();
        log.info("清除支付宝配置");
    }

    @Override
    public AliPayApiConfig getAliPayApiConfig() {
        AliPayApiConfig aliPayApiConfig = AliPayApiConfig.builder()
                .setAppId(aliPayBean.getAppId())
                .setAliPayPublicKey(aliPayBean.getPrivateKey())
                .setCharset("UTF-8")
                .setPrivateKey(aliPayBean.getPrivateKey())
                .setServiceUrl(aliPayBean.getServerUrl())
                .setSignType("RSA2")
                .build();
        return aliPayApiConfig;
    }

    @Override
    public Response appPay(AliPayParams params) {
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
        model.setBody(params.getBody());
        model.setSubject(params.getBody());
        model.setOutTradeNo(params.getOrderNo());
        model.setTimeoutExpress("30m");
        model.setTotalAmount(params.getAmount());
        model.setPassbackParams("callback params");
        model.setProductCode("QUICK_MSECURITY_PAY");
        try {
            AlipayTradeAppPayResponse response = AliPayApi.appPayToResponse(model, aliPayBean.getDomain() + notify_url);
            return new Response().data(response.getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return new Response().failure(e.getErrMsg());
        }
    }

    @Override
    public Response wapPay(HttpServletResponse response, AliPayParams params) {
        String returnUrl = aliPayBean.getDomain() + return_url;
        String notifyUrl = aliPayBean.getDomain() + notify_url;

        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setBody(params.getBody());
        model.setSubject(params.getBody());
        model.setTotalAmount(params.getAmount());
        model.setPassbackParams("1");
        model.setOutTradeNo(params.getOrderNo());
        model.setProductCode("QUICK_WAP_PAY");
        try {
            AliPayApi.wapPay(response, model, returnUrl, notifyUrl);
        } catch (Exception e) {
            e.printStackTrace();
            return new Response().failure(e.getMessage());
        }
        return null;
    }

    @Override
    public Response pcPay(HttpServletResponse response, AliPayParams params) {
        String returnUrl = aliPayBean.getDomain() + return_url;
        String notifyUrl = aliPayBean.getDomain() + notify_url;
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();

        model.setOutTradeNo(params.getOrderNo());
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        model.setTotalAmount(params.getAmount());
        model.setSubject(params.getAmount());
        model.setBody(params.getBody());
        model.setPassbackParams("passback_params");
        try {
            AliPayApi.tradePage(response, model, notifyUrl, returnUrl);
        } catch (Exception e) {
            e.printStackTrace();
            new Response().failure(e.getMessage());
        }
        return null;
    }

    @Override
    public Response tradePay(AliTradePayParams params) {
        String subject = null;
        String scene = params.getScene();
        if ("wave_code".equals(scene)) {
            subject = "支付宝声波支付";
        } else if ("bar_code".equals(scene)) {
            subject = "支付宝条形码支付";
        } else {
            return new Response().failure("参数错误");
        }
        String notifyUrl = aliPayBean.getDomain() + notify_url;

        AlipayTradePayModel model = new AlipayTradePayModel();
        model.setAuthCode(params.getAuthCode());
        model.setSubject(subject);
        model.setTotalAmount(params.getAmount());
        model.setOutTradeNo(params.getOrderNo());
        model.setScene(scene);
        try {
            AlipayTradePayResponse response = AliPayApi.tradePayToResponse(model, notifyUrl);
            return new Response().data(response);
        } catch (Exception e) {
            e.printStackTrace();
            return new Response().failure(e.getMessage());
        }
    }

    @Override
    public Response tradePrecreatePay(AliTradePrecreateParams precreatePay) {
        String notifyUrl = aliPayBean.getDomain() + notify_url;

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setSubject(precreatePay.getBody());
        model.setTotalAmount(precreatePay.getAmount());
        model.setStoreId(precreatePay.getStoreId());
        model.setTimeoutExpress("5m");
        model.setOutTradeNo(precreatePay.getOrderNo());
        try {
            String ResponseStr = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl).getBody();
            JSONObject json = new JSONObject(ResponseStr).getJSONObject("alipay_trade_precreate_response");
            if (json.getInt("code") == 10000) {
                return new Response().data( json.getStr("qr_code"));
            }
            return new Response().failure(json.getStr("sub_msg"));
        } catch (Exception e) {
            e.printStackTrace();
            return new Response().failure(e.getMessage());
        }
    }

    @Override
    public Response transfer(AliPayParams params) {
        AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
        model.setOutBizNo(params.getOrderNo());
        model.setPayeeType("ALIPAY_LOGONID");
        model.setPayeeAccount("tmseuj6887@sandbox.com");
        model.setAmount(params.getAmount());
        model.setPayerShowName("退款");
        model.setPayerRealName("沙箱环境");
        model.setRemark(params.getBody());
        try {
            boolean isSuccess = AliPayApi.transfer(model);
            return isSuccess ? new Response().success("成功") : new Response().failure("失败");
        } catch (Exception e) {
            e.printStackTrace();
            return new Response().failure(e.getMessage());
        }
    }

    @Override
    public Response tradeRefund(AliTradeRefundParams params) {
        try {
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(params.getOrderNo());
            model.setTradeNo(params.getTradeNo());
            model.setRefundAmount(params.getAmount());
            model.setRefundReason(params.getBody());
            AlipayTradeRefundResponse response = AliPayApi.tradeRefundToResponse(model);
            return new Response().data(response);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return new Response().failure(e.getErrMsg());
        }
    }

    @Override
    public Map<String, String> callback(HttpServletRequest request) {
        return AliPayApi.toMap(request);
    }
}
